﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Security.Cryptography;
using ConsultasDeDeguridad;
using consultasSql.consultasVarias;

namespace App_Code.consultasSql.ConsultasSeguridad
{
    public class Usuarios : CDarDataSet
    {

        private const string APP_PASS = "·/&(%&)%(%&ñ/$B$%VUYñ%V$%Y%$&$%&Y)";

        public int IdUsuario { get; set; }

        public DataTable SelectUsuarios()
        {
            string consulta = @"SELECT [id]
                    ,[idRol]
                    ,(SELECT nombre FROM ROLES R WHERE R.id = Usuarios.idRol) as NombreRol
                    ,[nombre]
                    ,[activo]
                    ,[password]
                  FROM [Usuarios]";

            SqlCommand command = new SqlCommand();
            command.CommandType = CommandType.Text;
            command.CommandText = consulta;

            return darDataSet(command).Tables[0];
        }

        public DataTable SelectUsuario(int idUsuario)
        {
            string consulta = @"SELECT [id]
                    ,[idRol]
                    ,(SELECT nombre FROM ROLES R WHERE R.id = Usuarios.idRol) as NombreRol
                    ,[nombre]
                    ,[activo]
                    ,[password]
                FROM [Usuarios]
                WHERE id = " + idUsuario;

            SqlCommand command = new SqlCommand();
            command.CommandType = CommandType.Text;
            command.CommandText = consulta;

            return darDataSet(command).Tables[0];
        }


        public void NuevoUsuario(int idRol, string nombreUsuario, bool activo, string clave)
        {
            
            using (SqlConnection objConexion = new SqlConnection(CCadenaConexionSql.cadConexion()))
            {
                if (objConexion.State == ConnectionState.Closed)
                    objConexion.Open();

                string consulta = @"INSERT INTO [Usuarios] 
                        ([idRol]
                        ,[nombre]
                        ,[activo]
                        ,[password])
                    SELECT 
                        @idRol,
                        @nombreUsuario,
                        @activo,
                        @clave";

                SqlCommand command = new SqlCommand();
                command.Connection = objConexion;
                command.Parameters.Add(new SqlParameter("@idRol", SqlDbType.Int));
                command.Parameters["@idRol"].Value = idRol;
                command.Parameters.Add(new SqlParameter("@nombreUsuario", SqlDbType.Text));
                command.Parameters["@nombreUsuario"].Value = nombreUsuario;
                command.Parameters.Add(new SqlParameter("@activo", SqlDbType.Bit));
                command.Parameters["@activo"].Value = activo;
                command.Parameters.Add(new SqlParameter("@clave", SqlDbType.Text));
                command.Parameters["@clave"].Value = Encrypt(clave);
                command.CommandType = CommandType.Text;
                command.CommandText = consulta;
                command.ExecuteNonQuery();

                objConexion.Close();
            }
        }

        public void ModificarUsuario(int IdUsuario, int idRol, string nombreUsuario, bool activo, string clave)
        {

            using (SqlConnection objConexion = new SqlConnection(CCadenaConexionSql.cadConexion()))
            {
                if (objConexion.State == ConnectionState.Closed)
                    objConexion.Open();

                string consulta = @"UPDATE [Usuarios] 
                    SET [idRol] = @idRol,
                        [nombre] = @nombreUsuario,
                        [activo] = @activo
                        " + (!string.IsNullOrEmpty(clave)? @", [password] =  @clave ": @"") + @"
                    WHERE [id] = @IdUsuario";

                SqlCommand command = new SqlCommand();
                command.Connection = objConexion;
                command.Parameters.Add(new SqlParameter("@IdUsuario", SqlDbType.Int));
                command.Parameters["@IdUsuario"].Value = IdUsuario;
                command.Parameters.Add(new SqlParameter("@idRol", SqlDbType.Int));
                command.Parameters["@idRol"].Value = idRol;
                command.Parameters.Add(new SqlParameter("@nombreUsuario", SqlDbType.Text));
                command.Parameters["@nombreUsuario"].Value = nombreUsuario;
                command.Parameters.Add(new SqlParameter("@activo", SqlDbType.Bit));
                command.Parameters["@activo"].Value = activo;
                if (!string.IsNullOrEmpty(clave))
                {
                    command.Parameters.Add(new SqlParameter("@clave", SqlDbType.Text));
                    command.Parameters["@clave"].Value = Encrypt(clave);
                }
                command.CommandType = CommandType.Text;
                command.CommandText = consulta;
                command.ExecuteNonQuery();

                objConexion.Close();
            }
        }

        // Encrypt a byte array into a byte array using a key and an IV 
        public static byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV)
        {
            MemoryStream ms = new MemoryStream();
            Rijndael alg = Rijndael.Create();
            alg.Key = Key;
            alg.IV = IV;
            CryptoStream cs = new CryptoStream(ms,
                                               alg.CreateEncryptor(), CryptoStreamMode.Write);
            cs.Write(clearData, 0, clearData.Length);
            cs.Close();
            byte[] encryptedData = ms.ToArray();
            return encryptedData;
        }

        // Encrypt a string into a string using a password 
        //    Uses Encrypt(byte[], byte[], byte[]) 
        public static string Encrypt(string clearText)
        {
            byte[] clearBytes =
                System.Text.Encoding.Unicode.GetBytes(clearText);
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(APP_PASS,
                                                              new byte[]
                                                              {
                                                                  0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d,
                                                                  0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76
                                                              });
            byte[] encryptedData = Encrypt(clearBytes,
                                           pdb.GetBytes(32), pdb.GetBytes(16));
            return Convert.ToBase64String(encryptedData);
        }

        public bool VerificarPermisoUsuario(string permisosRequeridos)
        {
            List<string> lPermisosRequeridos = new List<string>(permisosRequeridos.Split(','));
            CCPerfilesDeUsuario perfil = new CCPerfilesDeUsuario();
            DataTable dtPermisos = perfil.SelectPermisosDeUsuario(IdUsuario);
            foreach (DataRow row in dtPermisos.Rows)
            {
                if (row["nombre"] != null && lPermisosRequeridos.Contains(row["nombre"].ToString()))
                    return Convert.ToBoolean(row["leer"]) || Convert.ToBoolean(row["editar"]);
            }
            return false;
        }

        public bool VerificarPermisoUsuario(string permisosRequeridos, bool leer, bool editar)
        {
            List<string> lPermisosRequeridos = new List<string>(permisosRequeridos.Split(','));
            CCPerfilesDeUsuario perfil = new CCPerfilesDeUsuario();
            DataTable dtPermisos = perfil.SelectPermisosDeUsuario(IdUsuario);
            foreach (DataRow row in dtPermisos.Rows)
            {
                if (row["nombre"] != null && lPermisosRequeridos.Contains(row["nombre"].ToString()))
                {
                    return (leer && Convert.ToBoolean(row["leer"])) || (editar && Convert.ToBoolean(row["editar"]));  
                }
            }
            return false;
        }

        public bool ValidarUsuario(string nombre, string clave)
        {
            SqlCommand command = new SqlCommand();
            string consulta = @"SELECT *
                    FROM [Usuarios]
                    WHERE nombre = @nombre AND password = @password AND activo = 1";

            command.Parameters.Add(new SqlParameter("@nombre", SqlDbType.VarChar));
            command.Parameters["@nombre"].Value = nombre;
            command.Parameters.Add(new SqlParameter("@password", SqlDbType.VarChar));
            command.Parameters["@password"].Value = Encrypt(clave);

            command.CommandType = CommandType.Text;
            command.CommandText = consulta;
            DataTable dtDatos = darDataSet(command).Tables[0];

            if (dtDatos.Rows.Count > 0)
            {
                IdUsuario = Convert.ToInt32(dtDatos.Rows[0]["id"]);
                return true;
            }
            return false;
        }
    }
}